package io.github.jsp.executor.monitoring;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.jsp.executor.JobHandler;
import io.github.jsp.model.JobInfo;
import io.github.jsp.model.JobLog;
import io.github.jsp.service.monitoring.ServiceMonitoringService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class ServiceMonitoringJobHandler implements JobHandler {
    
    private static final Logger logger = LoggerFactory.getLogger(ServiceMonitoringJobHandler.class);
    
    @Autowired
    private ServiceMonitoringService monitoringService;
    
    private final ObjectMapper objectMapper = new ObjectMapper();
    
    @Override
    public void execute(JobInfo jobInfo, JobLog jobLog) throws Exception {
        logger.info("开始执行服务状态监控任务: {}", jobInfo.getId());
        
        List<ServiceConfig> services = parseServiceConfigs(jobInfo.getJobParam());
        
        if (services.isEmpty()) {
            logger.warn("未配置需要监控的服务");
            return;
        }
        
        int totalServices = services.size();
        int healthyCount = 0;
        int unhealthyCount = 0;
        List<String> failedServices = new ArrayList<>();
        
        for (ServiceConfig service : services) {
            try {
                boolean isHealthy = monitoringService.checkServiceHealth(service);
                
                if (isHealthy) {
                    healthyCount++;
                    logger.debug("服务 {}:{} 状态正常", service.getHost(), service.getPort());
                } else {
                    unhealthyCount++;
                    failedServices.add(service.getName() + "(" + service.getHost() + ":" + service.getPort() + ")");
                    logger.warn("服务 {}:{} 状态异常", service.getHost(), service.getPort());
                }
                
                // 记录监控结果
                monitoringService.recordMonitoringResult(service, isHealthy);
                
                // 处理告警
                if (!isHealthy) {
                    monitoringService.handleServiceAlert(service, "服务不可用");
                }
                
            } catch (Exception e) {
                unhealthyCount++;
                failedServices.add(service.getName() + "(" + service.getHost() + ":" + service.getPort() + ")");
                logger.error("监控服务 {}:{} 时发生异常", service.getHost(), service.getPort(), e);
                
                monitoringService.recordMonitoringResult(service, false);
                monitoringService.handleServiceAlert(service, "监控检查异常: " + e.getMessage());
            }
        }
        
        String resultMsg = String.format(
            "监控完成 - 总数:%d, 正常:%d, 异常:%d", 
            totalServices, healthyCount, unhealthyCount
        );
        
        if (!failedServices.isEmpty()) {
            resultMsg += ", 异常服务: " + String.join(", ", failedServices);
        }
        
        logger.info("服务监控任务执行完成: {}", resultMsg);
        
        // 如果有服务异常，可以选择抛出异常让任务标记为失败
        if (unhealthyCount > 0) {
            logger.warn("发现 {} 个服务状态异常", unhealthyCount);
            // throw new RuntimeException("存在服务状态异常: " + failedServices);
        }
    }
    
    private List<ServiceConfig> parseServiceConfigs(String jobParam) {
        List<ServiceConfig> services = new ArrayList<>();
        
        try {
            if (jobParam == null || jobParam.trim().isEmpty()) {
                return services;
            }
            
            JsonNode rootNode = objectMapper.readTree(jobParam);
            
            if (rootNode.has("services") && rootNode.get("services").isArray()) {
                for (JsonNode serviceNode : rootNode.get("services")) {
                    ServiceConfig config = new ServiceConfig();
                    config.setName(serviceNode.path("name").asText("Unknown"));
                    config.setHost(serviceNode.path("host").asText("localhost"));
                    config.setPort(serviceNode.path("port").asInt(80));
                    config.setProtocol(serviceNode.path("protocol").asText("tcp"));
                    config.setTimeoutMs(serviceNode.path("timeoutMs").asInt(5000));
                    config.setHealthCheckUrl(serviceNode.path("healthCheckUrl").asText(null));
                    config.setExpectedResponse(serviceNode.path("expectedResponse").asText(null));
                    config.setAlertEnabled(serviceNode.path("alertEnabled").asBoolean(true));
                    config.setAlertEmails(serviceNode.path("alertEmails").asText(null));
                    
                    services.add(config);
                }
            }
            
        } catch (Exception e) {
            logger.error("解析服务配置参数失败: {}", jobParam, e);
        }
        
        return services;
    }
    
    public static class ServiceConfig {
        private String name;
        private String host;
        private int port;
        private String protocol = "tcp"; // tcp, http, https
        private int timeoutMs = 5000;
        private String healthCheckUrl; // HTTP健康检查URL
        private String expectedResponse; // 期望的响应内容
        private boolean alertEnabled = true;
        private String alertEmails;
        
        // Getters and Setters
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        
        public String getHost() { return host; }
        public void setHost(String host) { this.host = host; }
        
        public int getPort() { return port; }
        public void setPort(int port) { this.port = port; }
        
        public String getProtocol() { return protocol; }
        public void setProtocol(String protocol) { this.protocol = protocol; }
        
        public int getTimeoutMs() { return timeoutMs; }
        public void setTimeoutMs(int timeoutMs) { this.timeoutMs = timeoutMs; }
        
        public String getHealthCheckUrl() { return healthCheckUrl; }
        public void setHealthCheckUrl(String healthCheckUrl) { this.healthCheckUrl = healthCheckUrl; }
        
        public String getExpectedResponse() { return expectedResponse; }
        public void setExpectedResponse(String expectedResponse) { this.expectedResponse = expectedResponse; }
        
        public boolean isAlertEnabled() { return alertEnabled; }
        public void setAlertEnabled(boolean alertEnabled) { this.alertEnabled = alertEnabled; }
        
        public String getAlertEmails() { return alertEmails; }
        public void setAlertEmails(String alertEmails) { this.alertEmails = alertEmails; }
        
        @Override
        public String toString() {
            return String.format("%s(%s:%d)", name, host, port);
        }
    }
}